/*
 * Copyright (C) 2010 by Lei Shi (sjtushi@gmail.com)
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License, 
 * version 2, or any later versions.
 * --------------------
 *
 * File: proc.h
 * Author: Lei Shi (sjtushi@gmail.com)
 *
 * Description: Provide some process related helper functions to 
 * xen-ps and xen-lsof
 *
 */
#ifndef _XEN_PROC_H_
#define _XEN_PROC_H_

#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/mman.h>

#include <xenaccess/xenaccess.h>
#include <xenaccess/xa_private.h>

#define MAX_COMMAND_LENGTH 30

/*
 * This part is guest kernel specfic offset definition, which could be 
 * retrieved from guest os, with help of findoffset.ko or get from 
 * include files:
 *      linux/sched.h         struct task_struct
 *      linux/fs.h            struct file
 *      linux/file.h          struct file_struct
 *      linux/mount.h         struct vfsmount
 *      linux/dcache.h        struct dentry, struct qstr
 */

/* struct task_struct */
/*
 * addr(task_struct->tasks) - addr(task_struct) 
 *  
 * tasks_offset means the offset of tasks member in task_struct.
 * This tasks member points to the list_head of tasks list;
 * This offset will help us to retrieve each processes from the
 * tasks list.
 */
#define TASKSTRUCT_TASKS_OFFSET      0x6c
/* addr(task_struct->pid) - addr(task_struct)  */
#define PROCESS_PID_OFFSET           0xa8
/* addr(task_struct->comm) - addr(task_struct)  */
#define PROCESS_NAME_OFFSET          0x18c
/* addr(task_struct->files) - addr(task_struct)  */
#define TASKSTRUCT_FILES_OFFSET     0x444

/* struct file_struct*/
/* addr(file_struct->fd_array) - addr(file_struct)*/
#define FILESTRUCT_FDARRAY_OFFSET    0x50
#define FILESTRUCT_FDTAB_OFFSET    0x8
/* struct fdtab*/
#define FDTAB_FD_OFFSET    0x8

/* struct file */
#define FILE_FFLAGS_OFFSET 0x18
#define FILE_FDENTRY_OFFSET 0x8
#define FILE_FVFSMOUNT_OFFSET 0xc

/* struct vfsmount*/
#define VFSMOUNT_ROOT_OFFSET 0x10
#define VFSMOUNT_MNTPOINT_OFFSET 0xc

/* struct dentry */
/* addr(dentry->d_name) - addr(dentry) */
#define DENTRY_DNAME_OFFSET          0x1c
#define DENTRY_PARENT_OFFSET 0x18

/* struct qstr */
/* addr(qstr->name) - addr(qstr) */
#define QSTR_NAME_OFFSET             0x8

#define STATUS_SUCCESS 0
#define STATUS_ERROR   1

#define CHECK_MAPPED_MEMORY(mem) \
   do { \
      if ((mem) == NULL) { xa_destroy(&xai); return STATUS_ERROR; }\
   } while(0)

#define CHECK_NULL_PTR(ptr) \
   do { \
      if ((ptr) == NULL) return STATUS_ERROR; \
   } while(0)

typedef uint32_t addr_t;

/* 
 * first prototype just support command and pid, as we use this prototype
 * as support helper application for xen-proc-monitor project.
 * Part of the prototype code is from XenAccess examples.
 */
typedef struct proc {
   uint32_t domid;
   pid_t pid;
   float cpu;
   float mem;
   uint32_t tty_num;
   time_t start_time;
   time_t time;
   char command[MAX_COMMAND_LENGTH];
} proc_t;

/* 
 * Get proc_t struct from task_struct address which is already mapped to 
 * domain0 memory space
 */
int getproc_from_guest(addr_t, proc_t*);

/* print out process information */
#define PRINT_PROC_PS_MODE 0
#define PRINT_PROC_LSOF_MODE 1
void print_proc(proc_t *, int mode);

/* init xa instance with domain id */
int init_xa_instance(xa_instance_t *, uint32_t);

/*
 * get pid with process command name in the runtime. 
 * used in xen-monitor load_profile, with this function, 
 * we could specfy only command name in profile.xml, don't need to know 
 * the pid.
 */
int getpid_from_cmd(uint32_t, const char *);

#endif //_XEN_PROC_H_

